home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1999 May
/
Macworld (1999-05).dmg
/
Updaters
/
SpriteWorld 2.2.1 Update
/
Source Updates
/
SpriteWorldUtils.c
< prev
Wrap
Text File
|
1999-02-25
|
20KB
|
811 lines
///--------------------------------------------------------------------------------------
// SpriteWorldUtils.c
//
// Portions are copyright: © 1991-94 Tony Myles, All rights reserved worldwide.
//
// Description: some utilities for creating worlds of sprites
///--------------------------------------------------------------------------------------
#ifndef __SWCOMMON__
#include "SWCommonHeaders.h"
#endif
#ifndef __QUICKDRAW__
#include <QuickDraw.h>
#endif
#ifndef __QDOFFSCREEN__
#include <QDOffscreen.h>
#endif
#ifndef __WINDOWS__
#include <Windows.h>
#endif
#ifndef __MEMORY__
#include <Memory.h>
#endif
#ifndef __GESTALT__
#include <Gestalt.h>
#endif
#ifndef __TOOLUTILS__
#include <ToolUtils.h>
#endif
#ifndef __RESOURCES__
#include <Resources.h>
#endif
#ifndef __ERRORS__
#include <Errors.h>
#endif
#ifndef __SPRITEWORLD__
#include "SpriteWorld.h"
#endif
#ifndef __SPRITELAYER__
#include "SpriteLayer.h"
#endif
#ifndef __SPRITE__
#include "Sprite.h"
#endif
#ifndef __SPRITEFRAME__
#include "SpriteFrame.h"
#endif
#ifndef __SPRITEWORLDUTILS__
#include "SpriteWorldUtils.h"
#endif
static OSErr gSWStickyError;
///--------------------------------------------------------------------------------------
// SWCreateRegionFromCIconMask
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateRegionFromCIconMask(
RgnHandle *maskRgn,
CIconHandle cIconH)
{
OSErr err = noErr;
RgnHandle tempMaskRgn;
char saveState;
BitMap iconMask;
*maskRgn = NULL;
saveState = HGetState((Handle)cIconH);
HLock((Handle)cIconH);
iconMask.rowBytes = (**cIconH).iconMask.rowBytes;
iconMask.bounds = (**cIconH).iconMask.bounds;
iconMask.baseAddr = (Ptr)(**cIconH).iconMaskData;
tempMaskRgn = NewRgn();
if (tempMaskRgn != NULL)
{
err = BitMapToRegion(tempMaskRgn, &iconMask);
if (err == noErr)
{
*maskRgn = tempMaskRgn;
}
else
{
DisposeRgn(tempMaskRgn);
}
}
else
{
err = MemError();
}
HSetState((Handle)cIconH, saveState);
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWCreateRegionFromPict
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateRegionFromPict(
RgnHandle *pictRgnH,
PicHandle srcPictH)
{
RgnHandle tempRgnH;
GWorldPtr saveGWorld,
offScrnGWld;
GDHandle saveGDH;
Rect frameRect;
ColorSearchUPP blackenColSearchUPP;
OSErr err;
GetGWorld(&saveGWorld, &saveGDH );
*pictRgnH = NULL;
frameRect = (**srcPictH).picFrame;
OffsetRect(&frameRect, -frameRect.left, -frameRect.top);
err = NewGWorld( &offScrnGWld, 1, &frameRect, nil, nil, 0 );
if (err == noErr)
{
blackenColSearchUPP = NewColorSearchProc( blackenColorSearch );
(void)LockPixels( GetGWorldPixMap(offScrnGWld) );
SetGWorld(offScrnGWld, nil);
AddSearch( blackenColSearchUPP );
EraseRect(&frameRect);
DrawPicture(srcPictH, &frameRect);
DelSearch( blackenColSearchUPP );
DisposeRoutineDescriptor( blackenColSearchUPP );
tempRgnH = NewRgn();
if (tempRgnH != NULL && err == noErr)
{
err = BitMapToRegion(tempRgnH, (BitMap*)*GetGWorldPixMap( offScrnGWld ) );
if (err == noErr)
{
*pictRgnH = tempRgnH;
}
else
{
DisposeRgn(tempRgnH);
}
}
else
{
if ( err == noErr )
err = MemError();
}
SetGWorld(saveGWorld, nil);
DisposeGWorld(offScrnGWld);
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWCreateRegionFromGWorldAndRect
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateRegionFromGWorldAndRect(
RgnHandle *maskRgn,
GWorldPtr maskGWorld,
Rect* frameRect)
{
OSErr err = noErr;
GDHandle saveGDH;
GWorldPtr saveGWorld,
tempMaskGWorld;
Rect tempMaskRect;
*maskRgn = NULL;
GetGWorld(&saveGWorld, &saveGDH);
tempMaskRect = *frameRect;
OffsetRect(&tempMaskRect, -tempMaskRect.left, -tempMaskRect.top);
err = SWCreateRegionFromGWorldAndRectStart( &tempMaskGWorld, tempMaskRect.right,
tempMaskRect.bottom );
if (err == noErr)
{
err = SWCreateRegionFromGWorldAndRectPartial( maskRgn, maskGWorld,
tempMaskGWorld, frameRect );
SWCreateRegionFromGWorldAndRectFinish( tempMaskGWorld );
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWCreateRegionFromGWorldAndRectStart
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateRegionFromGWorldAndRectStart(
GWorldPtr *tempMaskGWorld,
short maxWidth,
short maxHeight)
{
OSErr err = noErr;
Rect tempMaskRect;
SetRect( &tempMaskRect, 0, 0, maxWidth, maxHeight );
err = NewGWorld( tempMaskGWorld, 1, &tempMaskRect, nil, nil, 0 );
if (err == noErr)
{
(void)LockPixels( GetGWorldPixMap( *tempMaskGWorld ) );
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWCreateRegionFromGWorldAndRectFinish
///--------------------------------------------------------------------------------------
SW_FUNC void SWCreateRegionFromGWorldAndRectFinish(
GWorldPtr tempMaskGWorld)
{
if ( tempMaskGWorld != NULL )
{
DisposeGWorld(tempMaskGWorld);
}
}
///--------------------------------------------------------------------------------------
// SWCreateRegionFromGWorldAndRectPartial
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateRegionFromGWorldAndRectPartial(
RgnHandle *maskRgn,
GWorldPtr maskGWorld,
GWorldPtr tempMaskGWorld,
Rect* frameRect)
{
OSErr err = noErr;
GDHandle saveGDH;
GWorldPtr saveGWorld;
Rect tempMaskRect;
RgnHandle tempRgnH;
*maskRgn = NULL;
GetGWorld(&saveGWorld, &saveGDH);
tempMaskRect = *frameRect;
OffsetRect(&tempMaskRect, -tempMaskRect.left, -tempMaskRect.top);
(void)LockPixels( GetGWorldPixMap(maskGWorld) );
SetGWorld(maskGWorld, nil);
SetGWorld(tempMaskGWorld, nil);
CopyBits( (BitMap*)*GetGWorldPixMap( maskGWorld ),
(BitMap*)*GetGWorldPixMap( tempMaskGWorld ),
frameRect,
&tempMaskRect,
srcCopy,
nil );
tempRgnH = NewRgn();
if (tempRgnH != NULL)
{
err = BitMapToRegion(tempRgnH, (BitMap*)*GetGWorldPixMap( tempMaskGWorld ) );
UnlockPixels( GetGWorldPixMap(maskGWorld) );
if (err == noErr)
{
*maskRgn = tempRgnH;
}
else
{
DisposeRgn(tempRgnH);
}
}
else
{
err = MemError();
}
SetGWorld(saveGWorld, nil);
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWCreateGWorldFromPictResource
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateGWorldFromPictResource(
SpriteWorldPtr destSpriteWorld,
GWorldPtr *pictGWorldP,
short pictResID)
{
OSErr err = noErr;
PicHandle newPictH;
newPictH = GetPicture(pictResID);
if (newPictH != NULL)
{
err = SWCreateGWorldFromPict(destSpriteWorld, pictGWorldP, newPictH);
ReleaseResource((Handle)newPictH);
}
else
{
err = ResError();
if (err == noErr)
{
err = resNotFound;
}
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWCreateGWorldFromPict
// creates a offScreen GWorld and draws the specified pict into it
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateGWorldFromPict(
SpriteWorldPtr destSpriteWorld,
GWorldPtr *pictGWorld,
PicHandle pictH)
{
OSErr err;
GWorldPtr saveGWorld;
GDHandle saveGDevice;
GWorldPtr tempGWorld;
Rect pictRect;
short depth;
GDHandle theGDH;
*pictGWorld = NULL;
GetGWorld(&saveGWorld, &saveGDevice);
depth = destSpriteWorld->pixelDepth;
theGDH = destSpriteWorld->mainSWGDH;
pictRect = (**pictH).picFrame;
OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
if ( (**((**theGDH).gdPMap)).pixelSize == depth )
err = NewGWorld( &tempGWorld, depth, &pictRect, nil, theGDH, noNewDevice );
else
err = NewGWorld( &tempGWorld, depth, &pictRect, nil, nil, 0 );
if (err == noErr)
{
*pictGWorld = tempGWorld;
SetGWorld(tempGWorld, nil);
(void)LockPixels( GetGWorldPixMap(tempGWorld) );
EraseRect(&pictRect);
DrawPicture(pictH, &pictRect);
UnlockPixels( GetGWorldPixMap(tempGWorld) );
}
SetGWorld(saveGWorld, saveGDevice);
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWCreateGWorldFromCIconMask
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateGWorldFromCIconMask(
SpriteWorldPtr destSpriteWorld,
GWorldPtr *maskGWorldP,
CIconHandle cIconH)
{
OSErr err;
GWorldPtr saveGWorld;
GDHandle saveGDevice;
char saveState;
BitMap maskBitMap;
GWorldPtr tempGWorldP;
short depth;
GDHandle theGDH;
GetGWorld(&saveGWorld, &saveGDevice);
depth = destSpriteWorld->pixelDepth;
theGDH = destSpriteWorld->mainSWGDH;
saveState = HGetState((Handle)cIconH);
HLock((Handle)cIconH);
maskBitMap.rowBytes = (**cIconH).iconMask.rowBytes;
maskBitMap.bounds = (**cIconH).iconMask.bounds;
maskBitMap.baseAddr = (Ptr)(**cIconH).iconMaskData;
if ( (**((**theGDH).gdPMap)).pixelSize == depth )
err = NewGWorld( &tempGWorldP, depth, &maskBitMap.bounds, nil, theGDH, noNewDevice );
else
err = NewGWorld( &tempGWorldP, depth, &maskBitMap.bounds, nil, nil, 0 );
if (err == noErr)
{
SetGWorld(tempGWorldP, NULL);
(void)LockPixels( GetGWorldPixMap(tempGWorldP) );
CopyBits(&maskBitMap,
(BitMap*)*GetGWorldPixMap( tempGWorldP ),
&maskBitMap.bounds,
&maskBitMap.bounds,
srcCopy,
nil);
UnlockPixels( GetGWorldPixMap(tempGWorldP) );
*maskGWorldP = tempGWorldP;
}
SetGWorld(saveGWorld, saveGDevice);
HSetState((Handle)cIconH, saveState);
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWSetTransparentColor - allows you to set the background, or unmasked color
// of a sprite to a color other than white. Important: the sprite's background color
// MUST match the color you use with SWTransparentColor, or the Sprite won't load correctly.
///--------------------------------------------------------------------------------------
static RGBColor SWTransparentColor = { 0xFFFF, 0xFFFF, 0xFFFF }; // white
SW_FUNC void SWSetTransparentColor(const RGBColor *RGB)
{
SWTransparentColor = *RGB;
}
///--------------------------------------------------------------------------------------
// SWBlackenGWorld
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWBlackenGWorld( GWorldPtr oldGWorld )
{
GWorldPtr saveGWorld, newGWld;
GDHandle saveGDH;
Rect gwldRect;
GWorldFlags pixelState;
ColorSearchUPP blackenColSearchUPP;
OSErr err;
GetGWorld( &saveGWorld, &saveGDH );
gwldRect = oldGWorld->portRect;
pixelState = GetPixelsState( oldGWorld->portPixMap );
err = NewGWorld(&newGWld, 1, &gwldRect, nil, nil, 0 );
if ( err == noErr )
{
blackenColSearchUPP = NewColorSearchProc( blackenColorSearch );
(void)LockPixels( GetGWorldPixMap(newGWld) );
(void)LockPixels( GetGWorldPixMap(oldGWorld) );
SetGWorld( oldGWorld, nil ); ForeColor(blackColor); BackColor(whiteColor);
SetGWorld( newGWld, nil );
AddSearch( blackenColSearchUPP );
CopyBits ( (BitMap*)*GetGWorldPixMap( oldGWorld ),
(BitMap*)*GetGWorldPixMap( newGWld ),
&gwldRect,
&gwldRect,
srcCopy,
nil);
DelSearch( blackenColSearchUPP );
DisposeRoutineDescriptor( blackenColSearchUPP );
SetGWorld( oldGWorld, nil );
CopyBits ( (BitMap*)*GetGWorldPixMap( newGWld ),
(BitMap*)*GetGWorldPixMap( oldGWorld ),
&gwldRect,
&gwldRect,
srcCopy,
nil);
SetPixelsState( oldGWorld->portPixMap, pixelState );
DisposeGWorld( newGWld );
}
SetGWorld( saveGWorld, saveGDH );
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWWhitenGWorld - this function is called whenever SWBlackenGWorld is called to change
// all pixels in the Frame's image matching SWTransparentColor to white. This function,
// along with SWSetTransparentColor, allows you to load self-masking sprites without
// requiring the "transparent" color to be white. (With an additional delay, that is.)
///--------------------------------------------------------------------------------------
static unsigned short SWTransparentValue;
SW_FUNC OSErr SWWhitenGWorld( GWorldPtr oldGWorld )
{
GWorldPtr saveGWorld, newGWld;
GDHandle saveGDH;
Rect gwldRect;
GWorldFlags pixelState;
short pixelSize;
ColorSearchUPP whitenColSearchUPP;
OSErr err;
GetGWorld( &saveGWorld, &saveGDH );
pixelSize = (**(oldGWorld->portPixMap)).pixelSize;
// Compute index 0 for the current depth
if ( pixelSize <= 8 )
SWTransparentValue = 0xFFFF; // white, becomes index 0
else
SWTransparentValue = 0x0000; // black, is RGB 0
// If SWTransparentColor is already index 0, then this function is not needed
if (SWTransparentColor.red == SWTransparentValue &&
SWTransparentColor.green == SWTransparentValue &&
SWTransparentColor.blue == SWTransparentValue )
{
return noErr;
}
gwldRect = oldGWorld->portRect;
err = NewGWorld(&newGWld, pixelSize, &gwldRect, nil, nil, 0 );
if ( err == noErr )
{
pixelState = GetPixelsState( oldGWorld->portPixMap );
whitenColSearchUPP = NewColorSearchProc( whitenColorSearch );
(void)LockPixels( GetGWorldPixMap(newGWld) );
(void)LockPixels( GetGWorldPixMap(oldGWorld) );
SetGWorld( oldGWorld, nil ); ForeColor(blackColor); BackColor(whiteColor);
SetGWorld( newGWld, nil );
AddSearch( whitenColSearchUPP );
CopyBits ( (BitMap*)*GetGWorldPixMap( oldGWorld ),
(BitMap*)*GetGWorldPixMap( newGWld ),
&gwldRect,
&gwldRect,
srcCopy,
nil);
DelSearch( whitenColSearchUPP );
DisposeRoutineDescriptor( whitenColSearchUPP );
SetGWorld( oldGWorld, nil );
CopyBits ( (BitMap*)*GetGWorldPixMap( newGWld ),
(BitMap*)*GetGWorldPixMap( oldGWorld ),
&gwldRect,
&gwldRect,
srcCopy,
nil);
SetPixelsState( oldGWorld->portPixMap, pixelState );
DisposeGWorld( newGWld );
}
SetGWorld( saveGWorld, saveGDH );
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// blackenColorSearch
///--------------------------------------------------------------------------------------
pascal Boolean blackenColorSearch( RGBColor *RGB, long* position )
{
#pragma unused(position)
if ( RGB->red != SWTransparentColor.red ||
RGB->green != SWTransparentColor.green ||
RGB->blue != SWTransparentColor.blue )
{
RGB->red = RGB->green = RGB->blue = 0x0000; // masked (black)
}
else
{
RGB->red = RGB->green = RGB->blue = 0xFFFF; // transparent (white, index 0)
}
return ( false );
}
///--------------------------------------------------------------------------------------
// whitenColorSearch
///--------------------------------------------------------------------------------------
pascal Boolean whitenColorSearch( RGBColor *RGB, long* position )
{
#pragma unused(position)
// Convert pixels matching SWTransparentColor to 0, leaving others untouched
if ( RGB->red == SWTransparentColor.red &&
RGB->green == SWTransparentColor.green &&
RGB->blue == SWTransparentColor.blue )
{
RGB->red = RGB->green = RGB->blue = SWTransparentValue; // set to 0
}
return ( false );
}
#pragma mark -
///--------------------------------------------------------------------------------------
// SWClearStickyError
///--------------------------------------------------------------------------------------
SW_FUNC void SWClearStickyError(void)
{
gSWStickyError = 0;
}
///--------------------------------------------------------------------------------------
// SWStickyError
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWStickyError(void)
{
return gSWStickyError;
}
///--------------------------------------------------------------------------------------
// SWSetStickyIfError
///--------------------------------------------------------------------------------------
SW_FUNC void SWSetStickyIfError(OSErr errNum)
{
if ( errNum != noErr )
gSWStickyError = errNum;
}
///--------------------------------------------------------------------------------------
// SWHasSystem7
///--------------------------------------------------------------------------------------
SW_FUNC Boolean SWHasSystem7(void)
{
long versionNumber;
OSErr err;
err = Gestalt( gestaltSystemVersion, &versionNumber );
SWSetStickyIfError( err );
return (err == noErr) && (versionNumber >= 0x0700);
}
///--------------------------------------------------------------------------------------
// SWGetProcessorType
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWGetProcessorType(short *processorType)
{
long response;
Boolean powerMac = true;
short processor = -1;
OSErr err = noErr;
err = Gestalt(gestaltSysArchitecture,&response);
if (err == noErr)
{
switch (response)
{
case gestalt68k: powerMac = false; break;
case gestaltPowerPC: powerMac = true; break;
}
if (!powerMac)
{
// 68k
err = Gestalt(gestaltProcessorType,&response);
if (err == noErr)
{
switch (response)
{
case gestalt68000: processor = 68000; break;
case gestalt68010: processor = 68010; break;
case gestalt68020: processor = 68020; break;
case gestalt68030: processor = 68030; break;
case gestalt68040: processor = 68040; break;
}
}
}
else
{
// PPC
err = Gestalt(gestaltNativeCPUtype,&response);
if (err == noErr)
{
switch (response)
{
case gestaltCPU601: processor = 601; break;
case gestaltCPU603:
/* case gestaltCPU603e:*/ processor = 603; break;
case gestaltCPU604: processor = 604; break;
}
}
}
}
*processorType = processor;
return err;
}
///--------------------------------------------------------------------------------------
// SW_ABS - return the absolute value of a short
///--------------------------------------------------------------------------------------
SW_FUNC short SW_ABS(short theNum)
{
if (theNum >= 0)
return theNum;
else
return -theNum;
}
#if (SW_ASSERT_ON == 1)
///--------------------------------------------------------------------------------------
// SWAssertFail - called when the expression in SW_ASSERT() is false.
///--------------------------------------------------------------------------------------
void SWAssertFail(char* filename, int lineNum)
{
Str255 fileString = "\p";
Str15 lineString;
short n, result;
unsigned long junkTime;
NumToString((long)lineNum, lineString);
for (n = 0; filename[n] != 0; n++)
{
fileString[n+1] = filename[n];
}
fileString[0] += n;
SetCursor(&qd.arrow);
ShowCursor();
ParamText("\pAssertion failure! This program will now quit. The failure occurred here:",
fileString, lineString, "\pN/A");
result = StopAlert(kAssertAlertID, NULL);
if (result < 0)
{
SysBeep(1);
Delay(15, &junkTime); // Wait for beep to finish
}
ExitToShell();
}
#endif